package xyz.scootaloo.mono.base.lang

import cn.hutool.log.LogFactory
import java.io.Serializable

/**
 * 通用 controller 返回格式
 *
 * @see R 类型别名
 * @author flutterdash@qq.com
 * @since 2021/7/25 8:39
 *
 * @param success 操作是否成功
 * @param message 操作说明
 * @param code    操作代码
 * @param data    携带的数据
 * @param timestamp 时间戳
 */
data class Result<T>(
    val success: Boolean,
    val message: String,
    val code: Int,
    val data: T?,
    val timestamp: Long
) : Serializable {

    companion object StaticFactoryMethods {
        @JvmStatic
        private val log = LogFactory.get()

        fun <T> of(data: T): Result<T> = success(data)

        fun success(): Result<Void> = createResult(SC.SUCCESS, null)
        fun success(status: StatusCode): Result<Void> = createResult(status, null)
        fun <T> success(data: T): Result<T> = createResult(SC.SUCCESS, data)

        fun fail(): Result<Void> = createResult(SC.FAILED, null)
        fun fail(status: StatusCode): Result<Void> = createResult(status, null)

        fun <T> tryAndGet(errorStatus: SC = SC.SERVER_INTERNAL_ERROR, func: () -> T): R<T> {
            return try {
                val rsl = func()
                R.success(rsl)
            } catch (error: Throwable) {
                log.debug(error)
                createResult(errorStatus, null)
            }
        }

        private fun <T> createResult(status: StatusCode, data: T?): Result<T> {
            return Result(
                success = status.success,
                message = status.message,
                code = status.code,
                data = data,
                timestamp = System.currentTimeMillis()
            )
        }
    }
}
